const globalBuffer = {};
const eventWaitBuffer = {};

// 发送后，等待500毫秒，如果没有数据，则不再等待
const promisify = (cb) => () => {
  return Promise.race([
    new Promise((res, rej) => {
      cb((e, d) => {
        if (e) 
          rej(e);
        else 
          res(d);
      });
    }),
    new Promise((resolve, reject) => {
      setTimeout(() => {resolve([])}, 1000)
    })
  ])
};

// 根据usage和usagePage, 筛选HID设备
const filterHIDDevices = (devices) =>
  devices.filter((device) =>
    device.collections?.some(
      (collection) =>
        (collection.usagePage === 0x00c0 && collection.usage === 0x0001 ||
        collection.usagePage === 0xFF00 && collection.usage === 0x000E)
    )
  );

// 生成一个随机的地址
const getRandomAdress = () => {
  return (
    (self.crypto && self.crypto.randomUUID && self.crypto.randomUUID()) ||
    `path:${Math.random()}`
  );
};

// 添加设备信息
const addDeviceInfo = (device) => {
  const address = device._address || getRandomAdress();
  device._address = address;

  // 从设备信息中获取报告信息
  let reportId = 0;
  let reportSize = 0;
  let reportCount = 0;

  // 遍历所有集合，获取第一个有效的输出报告信息
  const collections = device.collections || [];
  for (const collection of collections) {
    if (collection.outputReports?.length) {
      const report = collection.outputReports[0];
      if (report.reportId !== undefined && report.items?.[0]) {
        reportId = report.reportId;
        reportSize = report.items[0].reportSize || 0;
        reportCount = report.items[0].reportCount || 0;
        break;
      }
    }
  }

  // 打印报告信息
  console.log("Device Report Info:", { reportId, reportSize, reportCount });

  const HIDDevice = {
    _device: device,
    interface: 0x0002,
    vendorId: device.vendorId ?? -1,
    productId: device.productId ?? -1,
    address,
    productName: device.productName,
    reportId,
    reportSize,
    reportCount
  };

  return (WebHid.hid_cache[address] = HIDDevice);
};

export const WebHid = {
  // HID设备缓存
  hid_cache: {},

  requestDevice: async (filters = []) => {
    // 请求用户选择 HID 设备
    const devices = await navigator.hid.requestDevice({
      filters: filters
    });
    // 添加设备
    devices.forEach(addDeviceInfo);
    const sortDevices = devices.sort((a, b) => a.productId - b.productId)
    return sortDevices[0];
  },

  getFilteredDevices: async () => {
    try {
      const hidDevices = filterHIDDevices(await navigator.hid.getDevices());
      return hidDevices;
    } catch (e) {
      return [];
    }
  },

  devices: async (requestAuthorize = false, filters = []) => {
    let devices = await WebHid.getFilteredDevices();
    if (devices.length === 0 || requestAuthorize) {
      try {
        await WebHid.requestDevice(filters);
      } catch (error) {
        return [];
      }
      devices = await WebHid.getFilteredDevices();
    }
    return devices.map(addDeviceInfo);
  }
};

export class HidDeivce {
  constructor(address) {
    this._hidDevice = undefined;
    this.reportId = -1;
    this.reportSize = -1;
    this.reportCount = -1;
    this.interface = -1;
    this.vendorId = -1;
    this.productId = -1;
    this.productName = "";
    this.address = "";
    this.openPromise = Promise.resolve();
    
    if (address == 'demo') {
      this.vendorId = 0x9a9a;
      this.productId = 0xbaba;
      this.productName = 'Test'
      return ;
    }

    this._hidDevice = WebHid.hid_cache[address];
    if (this._hidDevice) {
      this.vendorId = this._hidDevice.vendorId;
      this.productId = this._hidDevice.productId;
      this.address = this._hidDevice.address;
      this.interface = this._hidDevice.interface;
      this.productName = this._hidDevice.productName;
      this.reportId = this._hidDevice.reportId;
      this.reportSize = this._hidDevice.reportSize;
      this.reportCount = this._hidDevice.reportCount;
      globalBuffer[this.address] = globalBuffer[this.address] || [];
      eventWaitBuffer[this.address] = eventWaitBuffer[this.address] || [];
      if (!this._hidDevice._device.opened) {
        this.open();
      }
    }
  }

  async open() {
    if (this._hidDevice && !this._hidDevice._device.opened) {
      this.openPromise = this._hidDevice._device.open();
      this.setupListeners();
      try {
        await this.openPromise;
      } catch (error) {
       console.log(error) 
      }
    }
    return Promise.resolve();
  }

  // 添加Input事件监听
  addListeners(fn) {
    if (this._hidDevice) {
      this._hidDevice._device.oninputreport = fn;
    }
  }

  // 安装Input事件监听
  setupListeners() {
    if (this._hidDevice) {
      this._hidDevice._device.addEventListener("inputreport", (e) => {
        if (eventWaitBuffer[this.address].length !== 0) {
          // It should be impossible to have a handler in the buffer
          // that has a ts that happened after the current message
          // came in
          (eventWaitBuffer[this.address].shift())(
            new Uint8Array(e.data.buffer)
          );
        } else {
          globalBuffer[this.address].push({
            currTime: Date.now(),
            message: new Uint8Array(e.data.buffer),
          });
        }
      });
    }
  }

  read(fn) {
    eventWaitBuffer[this.address] = [];
    this.fastForwardGlobalBuffer(Date.now());
    if (globalBuffer[this.address].length > 0) {
      // this should be a noop normally
      fn(undefined, globalBuffer[this.address].shift()?.message);
    } else {
      eventWaitBuffer[this.address].push((data) => fn(undefined, data));
    }
  }

  readP = promisify((arg) => this.read(arg));

  fastForwardGlobalBuffer(time) {
    let messagesLeft = globalBuffer[this.address].length;
    while (messagesLeft) {
      messagesLeft--;
      // message in buffer happened before requested time
      if (globalBuffer[this.address][0].currTime < time) {
        globalBuffer[this.address].shift();
      } else {
        break;
      }
    }
  }

  // hid 写入数据
  async hid_write(buffer) {
    await this.openPromise;
    const data = new Uint8Array(buffer.slice(1));
    // 如果数据长度超过 reportCount，则截断数据
    if (data.length > this.reportCount) {
      const truncatedData = data.slice(0, this.reportCount);
      await this._hidDevice?._device.sendReport(this.reportId, truncatedData);
    } else {
      await this._hidDevice?._device.sendReport(this.reportId, data);
    }
  }

  // hid 发送 feature数据
  async hid_send_feature_report(reportId, buffer) {
    await this.openPromise;
    const data = new Uint8Array(buffer.slice(1));
    await this._hidDevice?._device.sendFeatureReport(this.reportId, data);
    return await this._hidDevice?._device.receiveFeatureReport(this.reportId);
  }

  // hid 获取 feature数据
  async hid_get_feature_report(reportId, buffer) {
    await this.openPromise;
    const data = new Uint8Array(buffer.slice(1));
    return await this._hidDevice?._device.receiveFeatureReport(reportId);
  }
}